/**
 * Easy to animate
 * @param {string} canvasId
 * @returns {Animation}
 */

var Animation = function(canvasId) {
    this.canvas = document.getElementById(canvasId);
    this.context = this.canvas.getContext("2d");
    this.t = 0;
    this.timeInterval = 0;
    this.startTime = 0;
    this.lastTime = 0;
    this.frame = 0;
    this.animating = false;
    // provided by Paul Irish
    window.requestAnimFrame = (function(callback) {
        return window.requestAnimationFrame ||
                window.webkitRequestAnimationFrame ||
                window.mozRequestAnimationFrame ||
                window.oRequestAnimationFrame ||
                window.msRequestAnimationFrame ||
                function(callback) {
                    window.setTimeout(callback, 1000 / 60);
                };
    })();
};

Animation.prototype.getContext = function() {
    return this.context;
};

Animation.prototype.getCanvas = function() {
    return this.canvas;
};

Animation.prototype.clear = function() {
    this.context.clearRect(0, 0, this.canvas.width, this.canvas.height);
};

Animation.prototype.setStage = function(func) {
    this.stage = func;
};

Animation.prototype.isAnimating = function() {
    return this.animating;
};

Animation.prototype.getFrame = function() {
    return this.frame;
};

Animation.prototype.start = function() {
    this.animating = true;
    var date = new Date();
    this.startTime = date.getTime();
    this.lastTime = this.startTime;
    if (this.stage !== undefined) {
        this.stage();
    }
    this.animationLoop();
};

Animation.prototype.stop = function() {
    this.animating = false;
};

Animation.prototype.getTimeInterval = function() {
    return this.timeInterval;
};

Animation.prototype.getTime = function() {
    return this.t;
};

Animation.prototype.getFps = function() {
    return this.timeInterval > 0 ? 1000 / this.timeInterval : 0;
};

Animation.prototype.animationLoop = function() {
    var that = this;
    this.frame++;
    var date = new Date();
    var thisTime = date.getTime();
    this.timeInterval = thisTime - this.lastTime;
    this.t += this.timeInterval;
    this.lastTime = thisTime;
    if (this.stage !== undefined) {
        this.stage();
    }
    if (this.animating) {
        requestAnimFrame(function() {
            that.animationLoop();
        });
    }
};

/*********** brAnimation ***********/

/**
 * Initiate animation
 * @param {string} canvasId 
 * @param {brObjectList} objectList
 * @returns {brAnimation}
 */
var _background;
var brAnimation = function(canvasId, objectList, start) {
    this.editable = false;
    this.drawPosition = 1;
    this.animation = new Animation(canvasId);
    this.context = this.animation.getContext();
    this.objectList = objectList;

    var branimation = this;
    this.animation.setStage(function() {
        this.clear();
        if (branimation.camera !== undefined) {
            branimation.camera.update(this);
        }
        if (branimation.background !== undefined)
            branimation.background.draw(this.context);
        var curObject = branimation.objectList.first;
        while (curObject !== null) {
            curObject.update(this);
            curObject.draw(this.context);
            curObject = curObject.next;
        }
        if (typeof (objBoundary) !== 'undefined')
            objBoundary.draw(this.context);
    });

    if (start === true)
        this.animation.start();
};

brAnimation.prototype.setCamera = function(camera) {
    this.camera = camera;
};

brAnimation.prototype.setBackground = function(background) {
    this.background = background;
    _background = background;
};

brAnimation.prototype.getContext = function() {
    return this.animation.getContext();
};

brAnimation.prototype.start = function() {
    return this.animation.start();
};

brAnimation.prototype.stop = function() {
    return this.animation.stop();
};

brAnimation.prototype.getTime = function() {
    return this.animation.getTime();
};

brAnimation.prototype.getFps = function() {
    return this.animation.getFps();
};

/*************** end ***************/